
package ajedrez;

import java.util.Enumeration;
import javax.swing.tree.DefaultMutableTreeNode;

public class JugadorArtificial
{
    private DefaultMutableTreeNode ArbolJugada = null;

    private int JugadorMAX;
    private int JugadorMIN;

    public static final int MAX = 1;
    public static final int MIN = -1;

    public static final float ALFA = -100000;
    public static final float BETA = 100000;

    public static final boolean ImprimirArbol = false;

    public JugadorArtificial(int pJugadorMAX, int pJugadorMIN)
    {
        this.JugadorMAX = pJugadorMAX;
        this.JugadorMIN = pJugadorMIN;
    }

    public int[] getJugada(int[] pConfigTablero)
    {
        Tablero partidaJuego = new Tablero(Tablero.ConvertirTablero(pConfigTablero));
        

        Generador Extensivo = new Generador();
        Extensivo.imprimir = false;
        ArbolJugada = Extensivo.GenerarMovimientos(partidaJuego, JugadorMAX, 0);

        Nodo nTiro = new Nodo();
        nTiro = this.MINIMAX_AlfaBeta(partidaJuego.Juego, ArbolJugada, JugadorMAX, ALFA, BETA, 0);

        /*
        Collections.reverse(nTiro.camino);
        System.out.print("Casilla de Tiro: " +  nTiro.CasillaMovimiento + " ");
        TreePath mejorCamino = new TreePath(nTiro.camino.toArray());
        Nodo node = (Nodo)mejorCamino.getLastPathComponent();
        */

        return Tablero.getTableroParaFrontEnd(nTiro.Juego);
    }


    private Nodo MINIMAX_AlfaBeta(int[] pConfigTablero, DefaultMutableTreeNode pNodoJugada, int piJugador, float piAlfa, float piBeta, int pProfundidad)
    {

        if(Generador.Suficiente(pConfigTablero))
        {
            Nodo nResultado = new Nodo(pConfigTablero);
            nResultado.valor = this.Bondad(pConfigTablero, piJugador);
            nResultado.camino.add(nResultado);

            if(ImprimirArbol)
                Impresora.ImprimirTablero(pConfigTablero, nResultado.Juego, nResultado.valor, pProfundidad);

            return nResultado;
        }
        else
        {
            if(pNodoJugada.isLeaf()) // Returns true if this node has no children.
            {
                Nodo nResultado = new Nodo(pConfigTablero);
                nResultado.valor = this.Bondad(pConfigTablero, piJugador);
                nResultado.camino.add(nResultado);

                if(ImprimirArbol)
                    Impresora.ImprimirTablero(pConfigTablero, nResultado.Juego, nResultado.valor, pProfundidad);

                return nResultado;
            }
            else
            {
                Nodo nMejorResultado = new Nodo();

                DefaultMutableTreeNode Sucesor = new DefaultMutableTreeNode();
                Nodo nResultadoSucesor = new Nodo();

                Enumeration Sucesores;
                Sucesores = pNodoJugada.children();

                nMejorResultado.valor = (piJugador == JugadorMAX)? ALFA : BETA; // Se inicializa el mejor valor.

                while(Sucesores.hasMoreElements())
                {
                    Sucesor = (DefaultMutableTreeNode)Sucesores.nextElement();

                    nResultadoSucesor = MINIMAX_AlfaBeta(((Nodo)Sucesor.getUserObject()).Juego, Sucesor, Generador.getJugadorContrario(piJugador), piAlfa, piBeta, pProfundidad + 1);

                    if(ImprimirArbol)
                        Impresora.ImprimirTablero(pConfigTablero, ((Nodo)Sucesor.getUserObject()).Juego, nResultadoSucesor.valor, pProfundidad);

                    if(piJugador == JugadorMAX) // if(piJugador == MAX)
                    {
                        if(nResultadoSucesor.valor > nMejorResultado.valor)
                        {
                            nMejorResultado.valor = nResultadoSucesor.valor;
                            nMejorResultado.camino = nResultadoSucesor.camino;
                            nMejorResultado.camino.add(nMejorResultado);
                            System.arraycopy(((Nodo)Sucesor.getUserObject()).Juego, 0, nMejorResultado.Juego, 0, 128);

                            
                            if(pProfundidad == 0)
                            {
                                Tablero.ImprimirMovimiento(pConfigTablero, ((Nodo) Sucesor.getUserObject()).Juego);
                                System.out.println("\n     Valor Nueva Jugada: " + nMejorResultado.valor);
                            }
                             
                        }

                        if(nResultadoSucesor.valor > piAlfa)
                            piAlfa = nMejorResultado.valor;
                        if(nResultadoSucesor.valor >= piBeta)
                            return nMejorResultado;
                    }
                    else // piJugador = MIN
                    {
                        if(nResultadoSucesor.valor < nMejorResultado.valor)
                        {
                            nMejorResultado.valor = nResultadoSucesor.valor;
                            nMejorResultado.camino = nResultadoSucesor.camino;
                            nMejorResultado.camino.add(nMejorResultado);
                            System.arraycopy(((Nodo)Sucesor.getUserObject()).Juego, 0, nMejorResultado.Juego, 0, 128);

                            
                            if(pProfundidad == 0)
                            {
                                Tablero.ImprimirMovimiento(pConfigTablero, ((Nodo) Sucesor.getUserObject()).Juego);
                                System.out.println("\n     Valor Nueva Jugada: " + nMejorResultado.valor);
                            }
                        }

                        if(nResultadoSucesor.valor < piBeta)
                            piBeta = nMejorResultado.valor;
                        if(nResultadoSucesor.valor <= piAlfa)
                            return nMejorResultado;
                    }
                }
                return nMejorResultado;
            }
        }
    }

    private float Bondad(int[] pConfigTablero, int piJugador)
    {
        float viValor;

        Tablero auxTablero = new Tablero(pConfigTablero);
        clsCalculaHeuristica Heuristica = new clsCalculaHeuristica();
        viValor = Heuristica.CalculaHeuristica(auxTablero,piJugador);

        return viValor;
    }
}
